package com.dnjn.happiness.oss.controller;
import com.dnjn.happiness.common.core.utils.StringUtils;
import com.dnjn.happiness.common.core.utils.file.MimeTypeUtils;
import com.dnjn.happiness.common.core.web.domain.AjaxResult;
import com.dnjn.happiness.common.security.annotation.InnerAuth;
import com.dnjn.happiness.oss.utils.MinioUtils;

import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.UUID;

@RestController
@RequestMapping("/minio")
public class MinioController {
    private static final Logger log = LoggerFactory.getLogger(MinioController.class);

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioUtils minioUtils;

    @Value("${minio.bucketName}")
    private String bucket;

    @Value("${minio.endpoint}")
    private String endpoint;


    @NotNull
    @InnerAuth
    @PostMapping(value = "/uploadMinioCommonInnerApi",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public AjaxResult uploadMinioCommonInnerApi(@RequestPart("file") MultipartFile file) throws Exception {
        // 判断上传文件是否为空
        if (null == file || 0 == file.getSize()) {
            return AjaxResult.error("上传文件不能为空");
        }
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            String filename =  UUID.randomUUID().toString()+ file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            String finalfilename = "images/" + filename;
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(finalfilename)
                    .bucket(bucket)
                    .contentType(file.getContentType())
                    .stream(inputStream, file.getSize(), -1).build();
            minioClient.putObject(objectArgs);
//            String filename = file.getOriginalFilename();
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", filename);
            ajax.put("fileUrl", endpoint + "/" + bucket + "/" + finalfilename);
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                throw new Exception(e);
            }
        }
    }

    /**
     * 文件上传
     *
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public AjaxResult upload(MultipartFile file) throws Exception {
        return uploadMinioCommon(file);
    }

    @NotNull
    public AjaxResult uploadMinioCommon(MultipartFile file) throws Exception {
        // 判断上传文件是否为空
        if (null == file || 0 == file.getSize()) {
            return AjaxResult.error("上传文件不能为空");
        }
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            String filename =  UUID.randomUUID().toString()+ file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            String finalfilename = "images/" + filename;
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(finalfilename)
                    .bucket(bucket)
                    .contentType(file.getContentType())
                    .stream(inputStream, file.getSize(), -1).build();
            minioClient.putObject(objectArgs);
//            String filename = file.getOriginalFilename();
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", filename);
            ajax.put("fileUrl", endpoint + "/" + bucket + "/" + finalfilename);
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                throw new Exception(e);
            }
        }
    }


    /**
     * 后台头像上传minio
     * @param file
     * @return
     * @throws Exception
     */
    @NotNull
    @InnerAuth
    @PostMapping(value = "/uploadAvatarMinio",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public AjaxResult uploadAvatarMinio(@RequestPart("file") MultipartFile file) throws Exception {
        // 判断上传文件是否为空
        if (null == file || 0 == file.getSize()) {
            return AjaxResult.error("上传文件不能为空");
        }
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            //获取后后缀名
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            if (StringUtils.isEmpty(extension))
            {
                extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
            }

            String filename =  UUID.randomUUID().toString()+ "." + extension;
            String finalfilename = "images/" + filename;
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(finalfilename)
                    .bucket(bucket)
                    .contentType(file.getContentType())
                    .stream(inputStream, file.getSize(), -1).build();
            minioClient.putObject(objectArgs);
//            String filename = file.getOriginalFilename();
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", filename);
            ajax.put("fileUrl", endpoint + "/" + bucket + "/" + finalfilename);
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                throw new Exception(e);
            }
        }
    }


    /**
     * 下载文件
     *
     * @param filename
     */
    @GetMapping("/download/{filename}")
    public void download(@PathVariable String filename, HttpServletResponse res) {

        try {
            InputStream fileInputStream = minioUtils.getObject(bucket, filename);
            res.setHeader("Content-Disposition", "attachment;filename=" + filename);
            res.setContentType("application/force-download");
            res.setCharacterEncoding("UTF-8");
            IOUtils.copy(fileInputStream, res.getOutputStream());
        } catch (Exception e) {
            log.error("下载失败");
            e.printStackTrace();
        }
/*
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucket)
                .object(filename).build();

        try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
            byte[] buf = new byte[1024];
            int len;
            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
                while ((len = response.read(buf)) != -1) {
                    os.write(buf, 0, len);
                }
                os.flush();
                byte[] bytes = os.toByteArray();
                res.setCharacterEncoding("utf-8");
                res.setContentType("application/force-download");// 设置强制下载不打开
                res.addHeader("Content-Disposition", "attachment;fileName=" + filename);
                try (ServletOutputStream stream = res.getOutputStream()) {
                    stream.write(bytes);
                    stream.flush();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }*/
    }

    @DeleteMapping("/delete/{fileName}")
    public AjaxResult delete(@PathVariable("fileName") String fileName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(fileName).build());
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.success("删除成功");
    }

    /**
     * 前端获取预签名URL
     */
    @GetMapping("/getPreSignature/{fileName}")
    public AjaxResult getPreSignature(@PathVariable String fileName) throws Exception {
        if (StringUtils.isEmpty(fileName)){
            return AjaxResult.error("文件名称不能为空");
        }
        String url = minioUtils.presignedUrl(bucket,fileName);
        return AjaxResult.success(url);
    }


}